<?php
use oxide\plugin\PluginAbstract;
use oxide\http\Context;
use oxide\ui\html;
use oxide\application\View;
use oxide\application\ViewController;

define('APPPLUGIN_DIR', dirname(__FILE__));

define('APPPLUGIN_SECTION_PK', 8);
define('APPPLUGIN_SECTION', 'section');
define('APPPLUGIN_COURSE', 'course');
define('APPPLUGIN_ACTIVE', 1);
define('APPPLUGIN_INACTIVE', 0);
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

class appPlugin extends PluginAbstract
{
	/**
	 *
	 * @param Context $context 
	 * @notifies 
	 * @listening  CommandInitialize, ContentDefaultControllerListQuery, ModuleContentInfoRenderContentEnd, 
	 *					ModuleContentInfoRenderFooterTermEnd, AdminContentPostForm, AdminContentPostContentDidSave, 
	 *					UserDefaultRegisterForm, UserDefaultUpdateForm, UserDefaultRegisterUserDidSave, 
	 *					UserDefaultUpdateDidsave, UserProfileContentEnd
	 */
	public function onInit(Context $context) 
	{	
		$this->register('CommandInitialize');
		
		// content module
		$this->register('ContentDefaultControllerListQuery');
		$this->register('ModuleContentInfoRenderFooterTermEnd');
		$this->register('ModuleContentInfoRenderContentEnd');
		
		// admin module
		$this->register('AdminContentPostForm');
		$this->register('AdminContentPostContentDidSave');		
		
		// user module
		$this->register('UserDefaultRegisterForm', 'userFormUpdate');
		$this->register('UserDefaultUpdateForm', 'userFormUpdate');
		$this->register('UserDefaultRegisterUserDidSave', 'userMetadataFormUpdate');
		$this->register('UserDefaultUpdateDidsave', 'userMetadataFormUpdate');
		$this->register('UserProfileContentEnd');
	}
	
	/**
	 * Setting up the user form update for registration and update info
	 * @param type $event
	 * @param type $sender
	 * @param type $args 
	 */
	public function userFormUpdate($event, $sender, $args)
	{
		// initialize the vars with args
		$user = $args['user'];
		$form = $args['form'];
		
		if($user->user_pk) {
			$metadata = $user->metadata();
			$address = ($metadata) ? $metadata->appPlugin_address : null;
			$phone = ($metadata) ? $metadata->appPlugin_phone : null;
		} else {
			$address = '';
			$phone = '';
		}

		if(!$user->user_pk) {
			// User Controller adds these fields automatically in update action
			// We only need to add them in registration
			$form->addControl(new html\InputControl('text', 'name', null, 'Name:'));
			$form->getInputValidator()->addRequired('name');
			$form->addControl(new html\InputControl('text', 'email', null, 'Email:'));
			$form->getInputValidator()->addRequired('email');
		}
		
		// Add these fields in registration and user info update
		$form->addControl(new html\TextareaControl('address', $address, 'Address:'));
		$form->getInputValidator()->addRequired('address');
		$form->addControl(new html\InputControl('text', 'phone', $phone, 'Phone:'));
		$form->getInputValidator()->addRequired('phone');
	}

	/**
	 * save/update user metadata during registration and update info
	 * @param type $event
	 * @param type $sender
	 * @param type $args 
	 */
	public function userMetadataFormUpdate($event, $sender, $args)
	{
		// initialize the vars with args
		$user = $args['user'];
		$values = $args['values'];
		
		// saving of the user metadata values
		$metadata = $user->metadata();
		$metadata->appPlugin_address = $values['address'];
		$metadata->appPlugin_phone = $values['phone'];
		$metadata->save();
	}
	
	/**
	 * Modifying the query based on required content listing data
	 * content listing shown in /content/type/course
	 * @param type $event
	 * @param type $sender
	 * @param type $args 
	 */
	public function onContentDefaultControllerListQuery($event, $sender, $args)
	{
		// initialize the vars for route and args
		$route = $route = $this->getContext()->route;
		$module = $route->module;
		$controller = $route->controller;
		$action = $route->action;
		$params = $route->params;
		$query = $args['query'];
			
		// if course, query for the listing of course sections with course as parent
		if (($module == 'content' && $controller == 'default' && $action == 'type' && $params[0] == 'course')) {	
			$query->distinct();
			$query->join('content c', array('c.parent_pk' => 'content.content_pk'), oxide\data\Connection::JOIN_LEFT);
			$query->where('c.type_pk', APPPLUGIN_SECTION_PK, \oxide\data\Connection::OP_EQ);

		}
	}
	
	/**
	 * in administration content entry, display the additional fields if the content type is section
	 * @param type $event
	 * @param type $sender
	 * @param type $args 
	 */
	public function onAdminContentPostForm($event, $sender, $args)
	{
		// initialize vars for form and content
		$content = $args['content'];
		$content_pk = $content->content_pk;	
		$form = $args['form'];

		// check if content type is section
		// if true, show the following fields with the content metadata
		if ($content->type_pk == APPPLUGIN_SECTION_PK) {
			if($content_pk) {
				$metadata = $content->metadata();
				$instructor = $metadata->appPlugin_instructor;
				$location = $metadata->appPlugin_location;
				$days = $metadata->appPlugin_days;
				$time = $metadata->appPlugin_time;
				$start = $metadata->appPlugin_start;
				$end = $metadata->appPlugin_end;
				$cost = $metadata->appPlugin_cost;
				$status = $metadata->appPlugin_status;
			} else {
				// if false, (for new content input), set all fields as empty
				$instructor = '';
				$location = '';
				$days = '';
				$time = '';
				$start = '';
				$end = '';
				$cost = '';
				$status = 0;
			}
			// add controls for the section fieldset entry
			$fieldset = 'Section:';
			$status_options = array(1 => 'Active', 0 => 'Inactive');
			$form->addControl(new html\InputControl('text', 'appPlugin_instructor', $instructor, 'Instructor:'), $fieldset);
			$form->addControl(new html\InputControl('text', 'appPlugin_location', $location, 'Location:'), $fieldset);
			$form->addControl(new html\InputControl('text', 'appPlugin_days', $days, 'Days:'), $fieldset);
			$form->addControl(new html\InputControl('text', 'appPlugin_time', $time, 'Time:'), $fieldset);
			$form->addControl(new html\InputControl('date', 'appPlugin_start', $start, 'Start:'), $fieldset);
			$form->addControl(new html\InputControl('date', 'appPlugin_end', $end, 'End:'), $fieldset);
			$form->addControl(new html\InputControl('text', 'appPlugin_cost', $cost, 'Cost:', array('size' => '10')), $fieldset);
			$form->addControl(new html\SelectControl('appPlugin_status', $status, 'Course Status', null, $status_options), $fieldset);
		}
	
	}
	
	/**
	 * saving the following fields to db, for those with no input, set to null
	 * @param type $event
	 * @param type $sender
	 * @param type $args 
	 */
	public function onAdminContentPostContentDidSave($event, $sender, $args)
	{
		// initialize vars with content and values
		$content = $args['content'];
		$values = $args['values'];
		$metadata = $content->metadata();


		// if fields are not empty, save the input values
		// if not, save values as null
		!empty($values['appPlugin_instructor']) ? $metadata->appPlugin_instructor = $values['appPlugin_instructor'] : null;
		!empty($values['appPlugin_location']) ? $metadata->appPlugin_location = $values['appPlugin_location'] : null;
		!empty($values['appPlugin_days']) ? $metadata->appPlugin_days = $values['appPlugin_days'] : null;
		!empty($values['appPlugin_time']) ? $metadata->appPlugin_time = $values['appPlugin_time'] : null;
		!empty($values['appPlugin_appPlugin_start']) ? $metadata->appPlugin_start = $values['appPlugin_start'] : null;
		!empty($values['end']) ? $metadata->appPlugin_end = $values['appPlugin_end'] : null;
		!empty($values['appPlugin_cost']) ? $metadata->appPlugin_cost = $values['appPlugin_cost'] : null;
		!empty($values['appPlugin_status']) ? $metadata->appPlugin_status = $values['appPlugin_status'] : null;
	}
	
	/**
	 * display the additional contents to display only at specified pages
	 * display login to register/register now in sections only
	 * listening to content/type/{section}
	 * @param type $event
	 * @param type $sender
	 * @param type $content 
	 */
	public function onModuleContentInfoRenderFooterTermEnd($event, $sender, $content = null)
	{
		// initialize vars 
		\oxide\application\View::load('_html', '_context');
		$context = $this->_context;
		$auth = $context->getAuth();
		$route = $this->getContext()->route;
		$params = $route->params;
		
		// if section, list additional attributes
		if (!empty($params[0]) && $params[0] == APPPLUGIN_SECTION) {
			
			$metadata = $content->metadata();
			$content_type = $content->content_type;
			$content_pk = $content->content_pk;
		
			if ($content_type == APPPLUGIN_SECTION) {
				// display the attributes for the content
				$this->_renderAttributeForContent($content);
			}
			// display the register or login for the content
			$this->_renderRegisterOrLoginForContent($content_pk);
		}
	}
	
	/**
	 * display the attributes (e.g. cost, location, etc) for the content
	 * @param type $content 
	 */
	private function _renderAttributeForContent($content)
	{
		// retrieve the list of keys from metadata
		$metadata = $content->metadata();
		$keys = array(
					 'appPlugin_cost', 
					 'appPlugin_instructor', 
					 'appPlugin_location', 
					 'appPlugin_days', 
					 'appPlugin_time',
					 'appPlugin_start', 
					 'appPlugin_end'
				);
		foreach ($keys as $key) {
			// remove the prefix and uppercase for the first letter
			// and display in dd/dt
			$uckey = ucfirst(str_replace('appPlugin_', '', $key)).':';
			_html::tag('dt', $uckey, array('title' => $key));
			_html::tag('dd', $metadata->$key. ' | ');
		}
		_html::tag('br', '');

	}

	/**
	 * display register/login for the content based on the condition if user is logged in or not
	 * @param int $content_pk 
	 */
	private function _renderRegisterOrLoginForContent($content_pk)
	{
		$user = _context::instance()->getAuth();
		
		// check if user is logged in
		// if true, register now
		// if not, login to register
		if (!$user->hasIdentity()) {
			_html::a('/user/login', 'Login to register');	
		} else {
			_html::a("/content/course/register/{$content_pk}", 'Register now');
		}
	}
	
	/**
	 * rendering the below content when loading the module content
	 * @param type $event
	 * @param type $sender
	 * @param type $content 
	 */
	public function onModuleContentInfoRenderContentEnd($event, $sender, $content = null)
	{
		// initialize vars
		\oxide\application\View::load('_html', '_context');
		$connection = $this->_context->getConnection();
		$route = $this->getContext()->route;
		$action = $route->action;
		$params = $route->params;
		$content_type = $content->content_type;
		$content_pk = $content->content_pk;
		
		// check if it is on /content/default/view/course
		if ($action == 'view' && $content_type == APPPLUGIN_COURSE) {
			// if true, query for list of sections to display
			$query = new oxide\data\sql\SelectQuery('content', $connection);
			$query->columns('content.*');
			$query->from('content');
			$query->where('content.parent_pk', $content_pk, \oxide\data\Connection::OP_EQ);
			$stmt = \module\content\model\Content::select($query);
			$contents = $stmt->fetchAll();
			
			// displaying the section contents
			foreach($contents as $section) {
				_html::start('section');
				_html::start('h4');
				_html::a('/content/view/' . $section['permalink'], $section['title']);
				_html::end();
				_html::tag('p', $section->content);
				
				_html::start('dl');
				// display the attributes of the section
				$this->_renderAttributeForContent($section);
				// display the register/login for the section
				$this->_renderRegisterOrLoginForContent($section->content_pk);
				_html::end();
			}
		}
	}
	
	/** 
	 * listinging for /content/course/register
	 * @param type $event
	 * @param type $sender
	 * @param type $args 
	 */
	public function onCommandInitialize($event, $sender, $args = null)
	{	
		// initialize vars
		\oxide\application\View::load('_context');
		$context = $this->_context;
		$connection = $this->_context->getConnection();
		$auth = _context::instance()->getAuth()->hasIdentity();
		$user = _context::instance()->getAuth()->getIdentity();
		$route = $this->getContext()->route;
		$action = $route->action;
		$params = $route->params;
		$message = '';
		
		// check on user's landing page
		// ie. listinging for /content/course/register
		if (($action == 'course') && (isset($params[0]) && $params[0] == 'register')) {
			// display message if course pk is not available or user not logged in
			if (empty($params[1]) || (!$auth)) {
				
				$message = 'Invalid page access.';
			} else{
				
				// get content pk and user pk
				$content_pk = $route->params[1];
				
				// check if user has previously made a registration for the course
				// query if user has already registered
				$query = new oxide\data\sql\SelectQuery('content_user_extension', $connection);
				$query->column('count(*) as extension_count');
				$query->where('content_user_extension.content_pk', $content_pk, \oxide\data\Connection::OP_EQ);
				$query->where('content_user_extension.user_pk', $user->user_pk, \oxide\data\Connection::OP_EQ);
				$stmt = \module\content\model\ContentUserExtension::select($query);
				$count = $stmt->fetch();
				
				// if user has already registered for current course, display message
				if ($count->extension_count > 0) {
					$message = 'You have already registered for this course previously, please check your registration status on your user profile.';
				} else {
					// if user has not already registered, proceed with the registration
					// find the user email to send the user an email upon successfully completion of registration
					$user_email = $user->email;

					// create new entry content_user_extension
					// set status = 0 
					$user_ext = new \module\content\model\ContentUserExtension();
					$user_ext->content_pk = $content_pk;
					$user_ext->user_pk = $user->user_pk;
					$user_ext->status = APPPLUGIN_INACTIVE;
					$success = $user_ext->save();

					// email admin
//					$from = "admin@alifsoft.com";
//					$to = array('to' => $user_email);
//					$subject = 'Course Registration';
//					$message = "{$user->username} has signed up for the course.";
//					oxide\util\Mailer::send($from, $to, $subject, $message);

					// registration confirmation page
					$message = 'Thanks for registering for the course';
				}
					
			}
			// render the script within the template
				
			// setup the view with script
			$script = APPPLUGIN_DIR .'/register-confirmation.phtml';
			$view = new View($script);
			$view->assign('message', $message);
			$view->assign('user', $user);

			$viewController = new ViewController($context, 'content', dirname(__FILE__));
			$context->getResponse()->addBody($viewController->render($view));
			$context->getResponse()->send();
			exit();
		}
				
	}

	
	/**
	 * displaying registered courses in user profile
	 * @param type $event
	 * @param type $sender
	 * @param type $args 
	 */
	public function onUserProfileContentEnd($event, $sender, $args)
	{
		// initialize vars
		\oxide\application\View::load('_html');
		$connection = $this->_context->getConnection();
		$user = $args;
		$user_pk = $user->user_pk;
		$metadata = $user->metadata();

		// query for all courses that user has registered (regardless of the payment status)
		$query = new oxide\data\sql\SelectQuery('content_user_extension', $connection);
		$query->column('content_user_extension.content_pk, content_user_extension.status, content.title');
      $query->where('content_user_extension.user_pk', $user_pk, \oxide\data\Connection::OP_EQ);
		$query->join('content', array('content.content_pk' => 'content_user_extension.content_pk'), oxide\data\Connection::JOIN_LEFT);
		$stmt = \module\content\model\ContentUserExtension::select($query);
		$courses = $stmt->fetchAll();
		
		// intialize the text to display based on the status
		$status_paid = 'Paid';
		$status_waiting = 'Awaiting for payment';
		
		// loop through the courses, and display course title and payment status
		foreach ($courses as $course) {
			$status_text = ($course['status']) ?  $status_paid : $status_waiting;
			$courses_registered[] = $course['title'].' - '. $status_text;
		}
		
		// creating the html for display on User profile
		_html::tag('h4', 'Profile');
		_html::tag('p', 'Name: '.$user->name);
		_html::tag('br', '');
		_html::tag('h4', 'Registered Courses');
		
		// check if user has registered for any courses
		// if no courses registered, display no courses text
		// otherwise, display the course title and status in a html list
		$no_courses_registered = 'No courses registered';
		!empty($courses_registered) ? $courses_registered : $courses_registered = $no_courses_registered;
		_html::ul($courses_registered);
		
	}
	

}
?>